home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / midas060 / src / wss.asm < prev    next >
Encoding:
Assembly Source File  |  1997-01-16  |  14.8 KB  |  671 lines

  1. ;*    WSS.ASM
  2. ;*
  3. ;* Windows Sound System Sound Device
  4. ;*
  5. ;* $Id: wss.asm,v 1.3 1997/01/16 18:41:59 pekangas Exp $
  6. ;*
  7. ;* Copyright 1996,1997 Housemarque Inc.
  8. ;*
  9. ;* This file is part of the MIDAS Sound System, and may only be
  10. ;* used, modified and distributed under the terms of the MIDAS
  11. ;* Sound System license, LICENSE.TXT. By continuing to use,
  12. ;* modify or distribute this file you indicate that you have
  13. ;* read the license and understand and accept it fully.
  14. ;*
  15.  
  16.  
  17.  
  18. IDEAL
  19. P386
  20. JUMPS
  21.  
  22. INCLUDE "lang.inc"
  23. INCLUDE "errors.inc"
  24. INCLUDE "sdevice.inc"
  25. INCLUDE "mixsd.inc"
  26. INCLUDE "dsm.inc"
  27.  
  28.  
  29. ;/***************************************************************************\
  30. ;*       enum wssFunctIDs
  31. ;*       ----------------
  32. ;* Description:  ID numbers for WSS Sound Device functions
  33. ;\***************************************************************************/
  34.  
  35. enum    wssFunctIDs \
  36.         ID_wssDetect = ID_wss, \
  37.         ID_wssInit, \
  38.         ID_wssClose
  39.  
  40.  
  41.  
  42. DATASEG
  43.  
  44. D_int   wssRate                         ; WSS actual output rate
  45.  
  46. wssSpd        DB    ?        ; WSS speed value
  47. wssOLMute    DB    ?        ; WSS old left channel mute value
  48. wssORMute    DB    ?        ; WSS old right channel mute value
  49.  
  50.  
  51. IFDEF __PASCAL__
  52. EXTRN   WSS : SoundDevice
  53. ENDIF
  54.  
  55.  
  56.  
  57.  
  58. IDATASEG
  59.  
  60.  
  61. WSSCONFIGBITS = sdUsePort or sdUseIRQ or sdUseDMA or sdUseMixRate or \
  62.                 sdUseOutputMode or sdUseDSM
  63. WSSMODEBITS = sdMono or sdStereo or sd8bit or sd16bit
  64.  
  65. ; If compiling for Pascal, Sound Device name is wssSD, from which the data
  66. ; will be copied to Sound Device WSS, defined in Pascal.
  67.  
  68. IFDEF   __PASCAL__
  69. SDNAM           equ     wssSD
  70. ELSE
  71. SDNAM           equ     WSS
  72. ENDIF
  73.  
  74. GLOBAL  SDNAM : SoundDevice
  75.  
  76. SDNAM   SoundDevice     < \
  77.  0,\
  78.  WSSCONFIGBITS,\
  79.  530h, 9, 3,\
  80.  1, 1,\
  81.  WSSMODEBITS,\
  82.  ptr_to wssSDName,\
  83.  ptr_to wssCardNames,\
  84.  4, ptr_to wssPortAddresses,\
  85.  ptr_to wssDetect,\
  86.  ptr_to wssInit,\
  87.  ptr_to wssClose,\
  88.  ptr_to dsmGetMixRate,\
  89.  ptr_to mixsdGetMode,\
  90.  ptr_to mixsdOpenChannels,\
  91.  ptr_to dsmCloseChannels,\
  92.  ptr_to dsmClearChannels,\
  93.  ptr_to dsmMute,\
  94.  ptr_to dsmPause,\
  95.  ptr_to dsmSetMasterVolume,\
  96.  ptr_to dsmGetMasterVolume,\
  97.  ptr_to mixsdSetAmplification,\
  98.  ptr_to mixsdGetAmplification,\
  99.  ptr_to dsmPlaySound,\
  100.  ptr_to dsmReleaseSound\
  101.  ptr_to dsmStopSound,\
  102.  ptr_to dsmSetRate,\
  103.  ptr_to dsmGetRate,\
  104.  ptr_to dsmSetVolume,\
  105.  ptr_to dsmGetVolume,\
  106.  ptr_to dsmSetSample,\
  107.  ptr_to dsmGetSample,\
  108.  ptr_to dsmSetPosition,\
  109.  ptr_to dsmGetPosition,\
  110.  ptr_to dsmGetDirection,\
  111.  ptr_to dsmSetPanning,\
  112.  ptr_to dsmGetPanning,\
  113.  ptr_to dsmMuteChannel,\
  114.  ptr_to dsmAddSample,\
  115.  ptr_to dsmRemoveSample,\
  116.  ptr_to mixsdSetUpdRate,\
  117.  ptr_to mixsdStartPlay,\
  118.  ptr_to mixsdPlay >
  119.  
  120.  
  121. LABEL    wssRates    WORD        ; sampling rates for WSS
  122.     DW     8000, 00h
  123.     DW     5513, 01h
  124.     DW    16000, 02h
  125.     DW    11025, 03h
  126.     DW    27429, 04h
  127.     DW    18900, 05h
  128.     DW    32000, 06h
  129.     DW    22050, 07h
  130.     DW        0, 08h        ; not supported
  131.     DW    37800, 09h
  132.     DW        0, 0Ah
  133.     DW    44100, 0Bh
  134.     DW    48000, 0Ch
  135.     DW    33075, 0Dh
  136.     DW     9600, 0Eh
  137.     DW     6615, 0Fh
  138.  
  139.  
  140. wssSDName       DB      "Windows Sound System Sound Device v1.30", 0
  141.  
  142. wssCardNames    DD      ptr_to wssName
  143.  
  144. wssName         DB      "Windows Sound System (Crystal/Analog CODEC)", 0
  145.  
  146. IFDEF __16__
  147. wssPortAddresses  DW    530h, 604h, 0E80h, 0F40h
  148. ELSE
  149. wssPortAddresses  DD    530h, 604h, 0E80h, 0F40h
  150. ENDIF
  151.  
  152.  
  153.  
  154. CODESEG
  155.  
  156.  
  157.  
  158. ;/***************************************************************************\
  159. ;*
  160. ;* Function:    WaitCODEC
  161. ;*
  162. ;* Description: Waits until the WSS CODEC finishes initializing
  163. ;*
  164. ;* Returns:    carry set if error, otherwise carry clear
  165. ;*
  166. ;* Destroys:    ax, cx, dx
  167. ;*
  168. ;\***************************************************************************/
  169.  
  170. PROC NOLANGUAGE WaitCODEC    NEAR    ; waits until CODEC finishes
  171.                     ;  initializing. Carry set if error
  172.     clc
  173.  
  174.         mov     _dx,[WSS.port]          ; dx = CODEC Index Address Register
  175.         add     _dx,4
  176.  
  177.         mov     _cx,8000h
  178.  
  179. @@wait: in    al,dx
  180.     or    al,al            ; wait until bit 7 is zero or 2000h
  181.     jns    @@ok            ; reads
  182.     loop    @@wait
  183.  
  184.     stc                ; if read 2000h times, there is a
  185.                     ; problem with the CODEC
  186. @@ok:    ret
  187.  
  188. ENDP
  189.  
  190.  
  191.  
  192.  
  193. ;/***************************************************************************\
  194. ;*
  195. ;* Function:    int wssDetect(int *result);
  196. ;*
  197. ;* Description: Detects Windows Sound System soundcard
  198. ;*
  199. ;* Returns:     MIDAS error code.
  200. ;*              1 stored to *result if WSS was detected, 0 if not.
  201. ;*
  202. ;\***************************************************************************/
  203.  
  204. PROC    wssDetect       _funct  result : _ptr
  205. USES    _bx
  206.  
  207.         LOADPTR es,_bx,[result]         ; store 0 in *result - no detection
  208.         mov     [_int _esbx],0
  209.  
  210. ;FIXME!!!
  211.  
  212.         xor     _ax,_ax
  213.     ret
  214. ENDP
  215.  
  216.  
  217.  
  218.  
  219. ;/***************************************************************************\
  220. ;*
  221. ;* Function:    int wssInit(unsigned mixRate, unsigned mode);
  222. ;*
  223. ;* Description: Initializes Windows Sound System
  224. ;*
  225. ;* Input:       unsigned mixRate        mixing rate
  226. ;*              unsigned mode           output mode (see enum sdMode)
  227. ;*
  228. ;* Returns:     MIDAS error code
  229. ;*
  230. ;\***************************************************************************/
  231.  
  232. PROC    wssInit         _funct  mixRate : _int, mode : _int
  233. USES    _si,_di,_bx
  234. LOCAL   wssMode : _int
  235.  
  236.     mov    [wssMode],0
  237.  
  238.     test    [mode],sd8bit        ; force 8-bit?
  239.     jnz    @@8b
  240.     or    [wssMode],sd16bit    ; if not, use 16 bits
  241.     jmp    @@bit
  242. @@8b:    or    [wssMode],sd8bit
  243.  
  244. @@bit:    test    [mode],sdMono        ; force mono?
  245.     jnz    @@mono
  246.     or    [wssMode],sdStereo    ; if not, use stereo
  247.     jmp    @@mst
  248. @@mono: or    [wssMode],sdMono
  249.  
  250. @@mst:
  251.         mov     _dx,[WSS.port]
  252.         add     _dx,4                   ; dx = CODEC Index Address Register
  253.     in    al,dx            ; is the CODEC busy?
  254.     or    al,al
  255.         jns     @@notbusy
  256.  
  257.         mov     _ax,errSDFailure        ; CODEC busy - failure
  258.         jmp     @@err
  259.  
  260. @@notbusy:
  261. IF 0
  262.     mov    al,0Ch            ; select misc. register
  263.     out    dx,al
  264.         inc     _dx
  265.     in    al,dx            ; AL = CODEC version
  266.  
  267.     mov    bl,al
  268.  
  269.     xor    al,al
  270.     out    dx,al            ; write 0 to misc. register
  271.     in    al,dx            ; and read it back
  272.     cmp    al,bl            ; if value changed this is not a
  273.         je      @@codecok               ; CODEC
  274.  
  275.         mov     _ax,errSDFailure        ; value changed - not a CODEC
  276.         jmp     @@err
  277. ENDIF
  278.  
  279. @@codecok:
  280.         mov     _bx,[WSS.IRQ]
  281.     cmp    bl,7
  282.     je    @@IRQ7
  283.     cmp    bl,9
  284.     je    @@IRQ9
  285.     cmp    bl,10
  286.     je    @@IRQ10
  287.     cmp    bl,11
  288.     je    @@IRQ11
  289.  
  290.         mov     _ax,errSDFailure        ; invalid IRQ number
  291.         jmp     @@err
  292.  
  293. @@IRQ7: mov    al,08h            ; IRQ value for CODEC configuration
  294.     jmp    @@IRQd
  295.  
  296. @@IRQ9: mov    al,10h            ; IRQ value for CODEC configuration
  297.     jmp    @@IRQd
  298.  
  299. @@IRQ10:
  300.     mov    al,18h            ; IRQ value for CODEC configuration
  301.     jmp    @@IRQd
  302.  
  303. @@IRQ11:
  304.     mov    al,20h            ; IRQ value for CODEC configuration
  305.  
  306.  
  307. @@IRQd:
  308.         mov     _bx,[WSS.DMA]
  309.     cmp    bl,0
  310.     je    @@DMA0
  311.     cmp    bl,1
  312.     je    @@DMA1
  313.     cmp    bl,3
  314.     je    @@DMA3
  315.  
  316.         mov     _ax,errSDFailure        ; invalid DMA number
  317.         jmp     @@err
  318.  
  319. @@DMA0: or    al,01h            ; DMA value for CODEC configuration
  320.     jmp    @@DMAd
  321.  
  322. @@DMA1: or    al,02h            ; DMA value for CODEC configuration
  323.     jmp    @@DMAd
  324.  
  325. @@DMA3: or    al,03h            ; DMA value for CODEC configuration
  326.  
  327. @@DMAd: mov     _dx,[WSS.port]
  328.     out    dx,al            ; set IRQ and DMA numbers
  329.  
  330.     ; WSS does _NOT_ seem to use any interrupts if using autoinit
  331.     ; DMA, so setting a IRQ-handler is unnecessary.
  332.  
  333.     ; now search for closest match of the mixing rate from the wssRates
  334.     ; table
  335.  
  336.         mov     _cx,16                  ; 16 possible values
  337.         xor     _si,_si                 ; pointer to rate table
  338.         mov     _dx,32767               ; distance from best match
  339.         xor     _bx,_bx                 ; rate number for best match
  340.  
  341. @@rl:
  342. IFDEF __32__
  343.         xor     eax,eax
  344. ENDIF
  345.         mov     ax,[wssRates+_si]       ; get a rate from table
  346.         add     _si,2
  347.         sub     _ax,[mixRate]           ; distance from wanted mixing rate
  348.     js    @@1            ; if this rate is smaller, ignore
  349.         cmp     _ax,_dx                 ; is distance greater than best match?
  350.     jae    @@1            ; if is, ignore
  351.  
  352.         mov     bx,[wssRates+_si]       ; rate number for this match
  353.         mov     _dx,_ax                 ; distance
  354.  
  355. @@1:    add     _si,2                   ; next rate
  356.     loop    @@rl
  357.  
  358.     mov    [wssSpd],bl        ; store rate number
  359.         shl     _bx,2
  360. IFDEF __32__
  361.         xor     eax,eax
  362. ENDIF
  363.         mov     ax,[wssRates+_bx]       ; get actual mixing rate from table
  364.         mov     [wssRate],_ax           ; store actual mixing rate
  365.  
  366.  
  367.         ; Take care of common initialization for all mixing Sound Devices:
  368.         push    es
  369.         call    mixsdInit LANG, [wssRate], [wssMode], [WSS.DMA]
  370.         pop     es
  371.         test    _ax,_ax
  372.         jnz     @@err
  373.  
  374.  
  375.         mov     _dx,[WSS.port]
  376.         add     _dx,4
  377.     mov    al,0Ah
  378.     out    dx,al
  379.         inc     _dx
  380.     in    al,dx            ; external mute on
  381.     or    al,40h
  382.     out    dx,al
  383.  
  384.         mov     _cx,1200h               ; delay to prevent clicks (value from
  385.                     ;  CODEC.ASM, ExtMute, WSS SDK 1.0)
  386. @@w1:    in    al,84h            ; a "safe" I/O port
  387.     loop    @@w1
  388.  
  389.  
  390.         ; Write zero to Pin Control (why?)
  391.         mov     _dx,[WSS.port]
  392.         add     _dx,4
  393.         mov     al,0Ah
  394.         out     dx,al
  395.         inc     _dx
  396.         xor     al,al
  397.         out     dx,al
  398.  
  399.  
  400.         ; Set single DMA mode and start autocalibration:
  401.  
  402.         mov     _dx,[WSS.port]
  403.         add     _dx,4
  404.         mov     al,49h                  ; enable MCE
  405.     out    dx,al
  406.         inc     _dx
  407.     mov    al,04h or 08h        ; single DMA channel, enable
  408.     out    dx,al            ; autocalibration
  409.  
  410.         ; Maybe we should do the port reading again? Shouldn't hurt anyone
  411.         ; anyhow:
  412.  
  413.         in      al,dx
  414.         in      al,dx
  415.  
  416.  
  417.         ; Now set playing rate and output format:
  418.  
  419.         mov     _dx,[WSS.port]
  420.         add     _dx,4                   ; enable MCE and select Clock and
  421.     mov    al,48h            ; Data Format Register (08h)
  422.     out    dx,al
  423.  
  424.         inc     _dx
  425.     mov    al,[wssSpd]        ; Clock Frequency Source & Divide
  426.     test    [wssMode],sd16bit
  427.     jz    @@no16
  428.     or    al,40h            ; 16-bit signed linear (0 - 8-bit
  429.                     ; unsigned linear)
  430. @@no16:
  431.     test    [wssMode],sdStereo    ; stereo?
  432.     jz    @@nostereo
  433.     or    al,10h            ; if yes, set stereo bit 1
  434.  
  435. @@nostereo:
  436.     out    dx,al
  437.  
  438.         ; Now according to GUS MAX SDK source we need to read from the CODEC
  439.         ; data port twice. Don't ask me why, but I really hope this solves
  440.         ; the problem in setting the sample rate...
  441.  
  442.         in      al,dx
  443.         in      al,dx
  444.  
  445.         ; Wait for CODEC initialization to complete:
  446.         call    WaitCODEC
  447.         jnc     @@initok
  448.         mov     _ax,errSDFailure
  449.         jmp     @@err
  450.  
  451. @@initok:
  452.         ; Now disable MCE:
  453.  
  454.         mov     _dx,[WSS.port]
  455.         add     _dx,4
  456.  
  457. @@disablemce:
  458.     mov    al,08h            ; disable MCE
  459.     out    dx,al
  460.         jmp short $+2
  461.         in      al,dx                   ; according to the GUS MAX SDK we need
  462.         cmp     al,08h                  ; to check the out got through - maybe
  463.         jne     @@disablemce            ; a bug in the CODEC?
  464.  
  465.  
  466.         ; Delay to ensure autocalibration has started:
  467.         mov     _cx,10000
  468. @@delay:
  469.         in      al,84h
  470.         loop    @@delay
  471.  
  472.  
  473.         ; Now we need to wait until autocalibration is finished. First check
  474.         ; that we actually do get the Test and Initialization register
  475.         ; number written to the index: (Again from GUS MAX SDK)
  476.  
  477. @@testinit:
  478.         mov     al,0Bh
  479.         out     dx,al
  480.         jmp short $+2
  481.         in      al,dx
  482.         cmp     al,0Bh
  483.         jne     @@testinit
  484.  
  485.         ; Now wait until bit 5 becomes zero in the register:
  486. @@wacal:
  487.         mov     al,0Bh
  488.         out     dx,al
  489.         inc     _dx                     ; wait until autocalibration is
  490.         in      al,dx                   ; finished
  491.         dec     _dx
  492.         test    al,32
  493.         jnz     @@wacal
  494.  
  495.  
  496.         ; Set Single DMA channel mode, disable autocalibration:
  497.         mov     _dx,[WSS.port]
  498.         add     _dx,4
  499.         mov     al,49h
  500.         out     dx,al
  501.         inc     _dx
  502.         mov     al,04h
  503.         out     dx,al
  504.  
  505.         ; Disable MCE:
  506.         dec     _dx
  507.         xor     al,al
  508.         out     dx,al
  509.  
  510.  
  511.         mov     _cx,1200h               ; delay to prevent clicks (value from
  512.                     ;  CODEC.ASM, ExtMute, WSS SDK 1.0)
  513. @@w2:    in    al,84h            ; a "safe" I/O port
  514.     loop    @@w2
  515.  
  516.         mov     _dx,[WSS.port]
  517.         add     _dx,4
  518.     mov    al,0Ah
  519.     out    dx,al
  520.         inc     _dx                     ; external mute off
  521.     in    al,dx
  522.     and    al,NOT 40h
  523.     out    dx,al
  524.  
  525.  
  526.         mov     _dx,[WSS.port]
  527.         add     _dx,6                   ; acknowledge CODEC interrupt (just
  528.     xor    al,al            ;  for safety...)
  529.     out    dx,al
  530.  
  531.  
  532.         mov     _dx,[WSS.port]
  533.         add     _dx,4                   ; select the lower base count
  534.     mov    al,0Fh
  535.     out    dx,al
  536.         inc     _dx
  537.     mov    al,255            ; set the low byte of count (DMAC
  538.     out    dx,al            ; takes care of wrapping)
  539.  
  540.         dec     _dx
  541.     mov    al,0Eh            ; select the upper base count
  542.     out    dx,al
  543.         inc     _dx
  544.     mov    al,255            ; set the high byte of count
  545.     out    dx,al
  546.  
  547.         ; Write 0 to Pin Control register: (?)
  548.         dec     _dx
  549.         mov     al,0Ah
  550.         out     dx,al
  551.         inc     _dx
  552.         xor     al,al
  553.         out     dx,al
  554.  
  555.         mov     _dx,[WSS.port]
  556.         add     _dx,4                   ; write to the Interface Configuration
  557.     mov    al,09h
  558.     out    dx,al
  559.  
  560.         inc     _dx
  561.     mov    al,05h            ; use DMA playback
  562.     out    dx,al
  563.  
  564.         dec     _dx
  565.     mov    al,06h
  566.     out    dx,al            ; mute off from left channel
  567.         inc     _dx
  568.     in    al,dx
  569.     mov    [wssOLMute],al
  570.     and    al,NOT 128
  571.     out    dx,al
  572.  
  573.         dec     _dx
  574.     mov    al,07h
  575.     out    dx,al            ; mute off from right channel
  576.         inc     _dx
  577.     in    al,dx
  578.     mov    [wssORMute],al
  579.     and    al,NOT 128
  580.     out    dx,al
  581.  
  582. @@ok:
  583.         xor     _ax,_ax                 ; WSS succesfully initialized
  584.         jmp     @@done
  585.  
  586.  
  587. @@err:  ERROR   ID_wssInit
  588.  
  589. @@done:
  590.     ret
  591. ENDP
  592.  
  593.  
  594.  
  595.  
  596. ;/***************************************************************************\
  597. ;*
  598. ;* Function:    int wssClose(void)
  599. ;*
  600. ;* Description: Uninitializes Windows Sound System
  601. ;*
  602. ;* Returns:     MIDAS error code
  603. ;*
  604. ;\***************************************************************************/
  605.  
  606. PROC    wssClose        _funct
  607. USES    _bx
  608.  
  609.         mov     _dx,[WSS.port]
  610.         add     _dx,4
  611.  
  612.     mov    al,06h
  613.     out    dx,al            ; old mute setting to left channel
  614.         inc     _dx
  615.     mov    al,[wssOLMute]
  616.     out    dx,al
  617.  
  618.         dec     _dx
  619.     mov    al,07h
  620.     out    dx,al            ; old mute setting to right channel
  621.         inc     _dx
  622.     mov    al,[wssORMute]
  623.     out    dx,al
  624.  
  625.         dec     _dx                     ; Pin Control Register
  626.     mov    al,0Ah
  627.     out    dx,al
  628.         inc     _dx
  629.     xor    al,al            ; turn off interrupts
  630.     out    dx,al
  631.  
  632.         inc     _dx
  633.     out    dx,al            ; acnowledge outstanding interrupts
  634.  
  635.         sub     _dx,2
  636.     mov    al,09h            ; Interface Configuration Register
  637.     out    dx,al
  638.         inc     _dx
  639.     xor    al,al            ; turn off CODEC's DMA
  640.     out    dx,al
  641.  
  642.         ; Take care of common uninitialization for all mixing Sound Devices:
  643.         push    es
  644.         call    mixsdClose
  645.         pop     es
  646.         test    _ax,_ax
  647.         jnz     @@err
  648.  
  649.         xor     _ax,_ax
  650.         jmp     @@done
  651.  
  652.  
  653. @@err:  ERROR   ID_wssClose
  654.  
  655. @@done:
  656.     ret
  657. ENDP
  658.  
  659.  
  660. ;* $Log: wss.asm,v $
  661. ;* Revision 1.3  1997/01/16 18:41:59  pekangas
  662. ;* Changed copyright messages to Housemarque
  663. ;*
  664. ;* Revision 1.2  1996/08/04 11:35:36  pekangas
  665. ;* All functions now preserve _bx
  666. ;*
  667. ;* Revision 1.1  1996/05/22 20:49:33  pekangas
  668. ;* Initial revision
  669. ;*
  670.  
  671. END